﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Learn_delegate
{
    class Program
    {
        static void Main(string[] args)
        {
            Calculator calculator = new Calculator();
            Action action = new Action(calculator.Report);
            calculator.Report();
            action.Invoke();
            action();

            Func<double, double, double> func = new Func<double, double, double>(calculator.Add);

            double x = 100;
            double y = 200;
            double z = 0;
            z = func(x, y);
            Console.WriteLine(z);

            /*
             委托是一种类 类是一种数据类型，所以委托也是一种数据类型
            它的声明方式与一般的类不同，主要是为了照顾可读性和 C/C++ 传统
            注意声明委托的位置
                避免写错地方结果声明变成嵌套类型
            委托与所封装的方法必须“类型兼容”

            delegate  double Calc(double x, double y);
                      double Add (double x, double y) {return x + y;}
                      double Sub (double x, double y) {return x - y;}
                      double Mul (double x, double y) {return x * y;}
             */

            Calculator calculator1 = new Calculator();
            Calc calc1 = new Calc(calculator1.Add);
            Calc calc2 = new Calc(calculator1.Sub);
            Calc calc3 = new Calc(calculator1.Mul);
            Calc calc4 = new Calc(calculator1.Div);

            Console.WriteLine(calc1.Invoke(x, y));
            Console.WriteLine(calc2.Invoke(x, y));
            Console.WriteLine(calc3.Invoke(x, y));
            Console.WriteLine(calc4.Invoke(x, y));
        }
    }

    public delegate double Calc(double a, double b);  // 自定义委托

    class Calculator
    {
        public void Report()
        {
            Console.WriteLine("I have 3 methods.");
        }

        public double Add(double a, double b)
        {
            return a + b;
        }
        public double Sub(double a, double b)
        {
            return a - b;
        }
        public double Mul(double a, double b)
        {
            return a * b;
        }
        public double Div(double a, double b)
        {
            return a / b;
        }
    }
}
